As hardware design grows in complexity, software components such as virtual machines (VMs) may be used to provide compatibility between different generations of hardware. VMs thus help reduce the complexity of hardware design while increasing hardware performance. In particular, VMs emulate physical properties of computing systems and provide compatibility between different hardware systems by adapting applications to run on a specific implementation of a certain hardware design.
Since a VM is implemented in software, a VM needs to refer to virtual memory addresses to access data stored in physical system memory. Virtual addresses are mapped to physical addresses in system memory by way of a translation look-aside buffer (TLB). TLB is a cache comprising certain page table entries that provide the mapping between a virtual address and a physical address. Thus, a physical address may be looked up in the TLB using a virtual address as a search key.
If the mapping for a virtual address is not stored in the TLB, the virtual address is determined based on data stored in a page table. A page table is a data structure that contains mapping information for every virtual address and is therefore very large in comparison to the TLB. Naturally, searching the page table for an address results in slower access speeds in comparison with searching the TLB.
A VM may be also implemented to optimize logic code so that the code can be executed more efficiently. When a code region requiring optimization (i.e., a hot code region) is executed by an application, a VM may optimize the code region and store the code region in a code cache. Subsequently, when the same hot code region is executed by the application, the processor is redirected to the optimized code stored in the code cache and executes the optimized code instead of the original non-optimized code.
An optimization related problem may arise with regard to systems that run applications with self-modifying code. A self-modifying code is a code that alters its instructions during execution. The presence of such feature in a code may result in a code region that is modified after the code region has already been optimized. Effectively, an optimized version of a self-modifying code may not correlate to the original code depending on when the self-modification event takes place.
Coherence between original code and optimized code can be guaranteed by invalidating all optimized code regions on pages that contain modified code, using an instruction TLB (iTLB). Unfortunately, this simple mechanism only guarantees coherence between original code and optimized code for pages with entries in the iTLB. Furthermore, since the iTLB is a type of cache, the amount of space in the iTLB is limited; substantial processing and bookkeeping overhead is introduced when large volumes of entries in the iTLB need to be swapped in and out, between cache memory and slower memory on disk storage, for example.
It is thus easy to see that guaranteeing coherency between original and optimal versions of a logic code can become highly inefficient when optimized code is frequently invalidated and then re-optimized (e.g., due to context switches). Accordingly, systems and methods are desired which can provide a more comprehensive and efficient mechanism for achieving coherence between dynamically optimized code and original code.
Features, elements, and aspects of the invention that are referenced by the same numerals in different figures represent the same, equivalent, or similar features, elements, or aspects, in accordance with one or more embodiments.